<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>方法 | 卡夫卡的岛上书店</title>
    <meta name="generator" content="VuePress 1.7.1">
    <link rel="icon" href="/blogs/blogs/favicon.ico">
    <meta name="description" content="卡夫卡的岛上书店是凯小默的个人博客，用于记录学习笔记、分享音乐、书籍、旅行等个人兴趣的站点。">
    <meta name="keywords" content="凯小默,凯小默的博客,博客,个人博客,vue,vuejs,vuepress,vuepress-theme-reco,卡夫卡,岛上书店,卡夫卡的岛上书店,音乐,电影,书籍">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    
    <link rel="preload" href="/blogs/assets/css/0.styles.7a0dfb7e.css" as="style"><link rel="preload" href="/blogs/assets/js/app.b6577c57.js" as="script"><link rel="preload" href="/blogs/assets/js/2.44f167e6.js" as="script"><link rel="preload" href="/blogs/assets/js/22.b69b7288.js" as="script"><link rel="preload" href="/blogs/assets/js/10.3a18c1d1.js" as="script"><link rel="prefetch" href="/blogs/assets/js/100.61348934.js"><link rel="prefetch" href="/blogs/assets/js/101.42e6df4a.js"><link rel="prefetch" href="/blogs/assets/js/102.6a2750c2.js"><link rel="prefetch" href="/blogs/assets/js/103.0ff299f9.js"><link rel="prefetch" href="/blogs/assets/js/104.3b570960.js"><link rel="prefetch" href="/blogs/assets/js/105.37d6cfdf.js"><link rel="prefetch" href="/blogs/assets/js/106.1dfdd5aa.js"><link rel="prefetch" href="/blogs/assets/js/107.27a87e39.js"><link rel="prefetch" href="/blogs/assets/js/108.36db6d97.js"><link rel="prefetch" href="/blogs/assets/js/109.bd3f60c5.js"><link rel="prefetch" href="/blogs/assets/js/11.82fbfbb6.js"><link rel="prefetch" href="/blogs/assets/js/110.5633993c.js"><link rel="prefetch" href="/blogs/assets/js/111.4557a9aa.js"><link rel="prefetch" href="/blogs/assets/js/112.f71fc74e.js"><link rel="prefetch" href="/blogs/assets/js/113.d999e553.js"><link rel="prefetch" href="/blogs/assets/js/114.4410179e.js"><link rel="prefetch" href="/blogs/assets/js/115.1e9773e3.js"><link rel="prefetch" href="/blogs/assets/js/116.212695ab.js"><link rel="prefetch" href="/blogs/assets/js/117.006d9038.js"><link rel="prefetch" href="/blogs/assets/js/118.b47f7110.js"><link rel="prefetch" href="/blogs/assets/js/119.286ab222.js"><link rel="prefetch" href="/blogs/assets/js/12.8b07f727.js"><link rel="prefetch" href="/blogs/assets/js/120.90205ba7.js"><link rel="prefetch" href="/blogs/assets/js/121.5beb3d8c.js"><link rel="prefetch" href="/blogs/assets/js/122.7ab018ab.js"><link rel="prefetch" href="/blogs/assets/js/123.843ac3bb.js"><link rel="prefetch" href="/blogs/assets/js/124.f04c46cb.js"><link rel="prefetch" href="/blogs/assets/js/125.6d88bedc.js"><link rel="prefetch" href="/blogs/assets/js/126.5bfac816.js"><link rel="prefetch" href="/blogs/assets/js/127.2a7e4b14.js"><link rel="prefetch" href="/blogs/assets/js/128.59661175.js"><link rel="prefetch" href="/blogs/assets/js/129.36dade94.js"><link rel="prefetch" href="/blogs/assets/js/13.6b3d22fb.js"><link rel="prefetch" href="/blogs/assets/js/130.f61ee012.js"><link rel="prefetch" href="/blogs/assets/js/131.5ed7262d.js"><link rel="prefetch" href="/blogs/assets/js/132.9bf07050.js"><link rel="prefetch" href="/blogs/assets/js/133.cd691efa.js"><link rel="prefetch" href="/blogs/assets/js/134.d4b30918.js"><link rel="prefetch" href="/blogs/assets/js/135.0889a1e6.js"><link rel="prefetch" href="/blogs/assets/js/136.69cb5efa.js"><link rel="prefetch" href="/blogs/assets/js/137.0d5860ba.js"><link rel="prefetch" href="/blogs/assets/js/138.0ddd14b5.js"><link rel="prefetch" href="/blogs/assets/js/139.042053c1.js"><link rel="prefetch" href="/blogs/assets/js/14.5d4e7a64.js"><link rel="prefetch" href="/blogs/assets/js/140.58984eaa.js"><link rel="prefetch" href="/blogs/assets/js/141.e517a3c5.js"><link rel="prefetch" href="/blogs/assets/js/142.3ac7fced.js"><link rel="prefetch" href="/blogs/assets/js/143.2732c57b.js"><link rel="prefetch" href="/blogs/assets/js/144.c88252d1.js"><link rel="prefetch" href="/blogs/assets/js/145.ad5589ae.js"><link rel="prefetch" href="/blogs/assets/js/146.40250fde.js"><link rel="prefetch" href="/blogs/assets/js/147.4fa20f68.js"><link rel="prefetch" href="/blogs/assets/js/148.efce1d32.js"><link rel="prefetch" href="/blogs/assets/js/149.f8b4e8e9.js"><link rel="prefetch" href="/blogs/assets/js/15.dd270c50.js"><link rel="prefetch" href="/blogs/assets/js/150.5e2c993b.js"><link rel="prefetch" href="/blogs/assets/js/151.26e2eb05.js"><link rel="prefetch" href="/blogs/assets/js/152.466c45c9.js"><link rel="prefetch" href="/blogs/assets/js/153.fb4bc7db.js"><link rel="prefetch" href="/blogs/assets/js/154.1581847e.js"><link rel="prefetch" href="/blogs/assets/js/155.598b4be9.js"><link rel="prefetch" href="/blogs/assets/js/156.348bd2b2.js"><link rel="prefetch" href="/blogs/assets/js/157.f621e49c.js"><link rel="prefetch" href="/blogs/assets/js/158.2b5f3013.js"><link rel="prefetch" href="/blogs/assets/js/159.6214913e.js"><link rel="prefetch" href="/blogs/assets/js/16.89c35137.js"><link rel="prefetch" href="/blogs/assets/js/160.00f7d0b6.js"><link rel="prefetch" href="/blogs/assets/js/161.04fe0063.js"><link rel="prefetch" href="/blogs/assets/js/162.2f60c4fc.js"><link rel="prefetch" href="/blogs/assets/js/163.d24d684b.js"><link rel="prefetch" href="/blogs/assets/js/164.a22c8ce6.js"><link rel="prefetch" href="/blogs/assets/js/165.29df00c2.js"><link rel="prefetch" href="/blogs/assets/js/166.266719f5.js"><link rel="prefetch" href="/blogs/assets/js/167.6fd7fee8.js"><link rel="prefetch" href="/blogs/assets/js/168.a172abbc.js"><link rel="prefetch" href="/blogs/assets/js/169.198b869c.js"><link rel="prefetch" href="/blogs/assets/js/17.59a993c4.js"><link rel="prefetch" href="/blogs/assets/js/170.998b2f15.js"><link rel="prefetch" href="/blogs/assets/js/171.92c054fa.js"><link rel="prefetch" href="/blogs/assets/js/172.731e2473.js"><link rel="prefetch" href="/blogs/assets/js/173.ba3ff148.js"><link rel="prefetch" href="/blogs/assets/js/174.2ae915d3.js"><link rel="prefetch" href="/blogs/assets/js/175.dfc3341b.js"><link rel="prefetch" href="/blogs/assets/js/176.81677471.js"><link rel="prefetch" href="/blogs/assets/js/177.814d7c87.js"><link rel="prefetch" href="/blogs/assets/js/178.24b1b2df.js"><link rel="prefetch" href="/blogs/assets/js/179.95268dfb.js"><link rel="prefetch" href="/blogs/assets/js/18.3c7337d8.js"><link rel="prefetch" href="/blogs/assets/js/180.462b461f.js"><link rel="prefetch" href="/blogs/assets/js/181.1ee71c3d.js"><link rel="prefetch" href="/blogs/assets/js/182.78063d7a.js"><link rel="prefetch" href="/blogs/assets/js/183.a19bc5ff.js"><link rel="prefetch" href="/blogs/assets/js/184.7360e730.js"><link rel="prefetch" href="/blogs/assets/js/185.91647c2b.js"><link rel="prefetch" href="/blogs/assets/js/186.b4d5fbd8.js"><link rel="prefetch" href="/blogs/assets/js/187.cea7dd6e.js"><link rel="prefetch" href="/blogs/assets/js/188.0f474d25.js"><link rel="prefetch" href="/blogs/assets/js/189.9f1ea486.js"><link rel="prefetch" href="/blogs/assets/js/19.27625bd6.js"><link rel="prefetch" href="/blogs/assets/js/190.741abdcd.js"><link rel="prefetch" href="/blogs/assets/js/191.fb951065.js"><link rel="prefetch" href="/blogs/assets/js/192.992c1657.js"><link rel="prefetch" href="/blogs/assets/js/193.13763adc.js"><link rel="prefetch" href="/blogs/assets/js/194.0e541d84.js"><link rel="prefetch" href="/blogs/assets/js/195.56068487.js"><link rel="prefetch" href="/blogs/assets/js/196.2b45f3a3.js"><link rel="prefetch" href="/blogs/assets/js/197.dbdaf478.js"><link rel="prefetch" href="/blogs/assets/js/198.4d38424f.js"><link rel="prefetch" href="/blogs/assets/js/199.60402a1e.js"><link rel="prefetch" href="/blogs/assets/js/20.6a1cd4b0.js"><link rel="prefetch" href="/blogs/assets/js/200.022d44fb.js"><link rel="prefetch" href="/blogs/assets/js/201.f709417f.js"><link rel="prefetch" href="/blogs/assets/js/202.fcf42b43.js"><link rel="prefetch" href="/blogs/assets/js/203.46ea886e.js"><link rel="prefetch" href="/blogs/assets/js/204.fb70e5a5.js"><link rel="prefetch" href="/blogs/assets/js/205.c81e62f5.js"><link rel="prefetch" href="/blogs/assets/js/206.55e7bb6c.js"><link rel="prefetch" href="/blogs/assets/js/207.4cd290a8.js"><link rel="prefetch" href="/blogs/assets/js/208.23b65267.js"><link rel="prefetch" href="/blogs/assets/js/209.ba939372.js"><link rel="prefetch" href="/blogs/assets/js/21.ece1fdce.js"><link rel="prefetch" href="/blogs/assets/js/210.4de738a7.js"><link rel="prefetch" href="/blogs/assets/js/211.4b462ed7.js"><link rel="prefetch" href="/blogs/assets/js/212.14ec6854.js"><link rel="prefetch" href="/blogs/assets/js/213.e6f24ac6.js"><link rel="prefetch" href="/blogs/assets/js/214.3489ed46.js"><link rel="prefetch" href="/blogs/assets/js/215.bfbf9fb7.js"><link rel="prefetch" href="/blogs/assets/js/216.4c4f8976.js"><link rel="prefetch" href="/blogs/assets/js/217.ebc4029f.js"><link rel="prefetch" href="/blogs/assets/js/218.5e55974b.js"><link rel="prefetch" href="/blogs/assets/js/219.73beef2d.js"><link rel="prefetch" href="/blogs/assets/js/220.1094b5c6.js"><link rel="prefetch" href="/blogs/assets/js/221.d83bbdbc.js"><link rel="prefetch" href="/blogs/assets/js/222.00644dba.js"><link rel="prefetch" href="/blogs/assets/js/223.31d8fcdf.js"><link rel="prefetch" href="/blogs/assets/js/224.aef72f74.js"><link rel="prefetch" href="/blogs/assets/js/225.1c23f9c7.js"><link rel="prefetch" href="/blogs/assets/js/226.2a24ccd8.js"><link rel="prefetch" href="/blogs/assets/js/227.61b776c4.js"><link rel="prefetch" href="/blogs/assets/js/228.cccd80f8.js"><link rel="prefetch" href="/blogs/assets/js/229.3264b446.js"><link rel="prefetch" href="/blogs/assets/js/23.ff379a76.js"><link rel="prefetch" href="/blogs/assets/js/230.734e70e1.js"><link rel="prefetch" href="/blogs/assets/js/231.387b34d7.js"><link rel="prefetch" href="/blogs/assets/js/232.01029451.js"><link rel="prefetch" href="/blogs/assets/js/233.d970f564.js"><link rel="prefetch" href="/blogs/assets/js/234.9a274128.js"><link rel="prefetch" href="/blogs/assets/js/235.e9655c87.js"><link rel="prefetch" href="/blogs/assets/js/236.dd33b8e8.js"><link rel="prefetch" href="/blogs/assets/js/237.a762a9b9.js"><link rel="prefetch" href="/blogs/assets/js/238.4f341fc8.js"><link rel="prefetch" href="/blogs/assets/js/239.445f4a71.js"><link rel="prefetch" href="/blogs/assets/js/24.d6f90646.js"><link rel="prefetch" href="/blogs/assets/js/240.8b6ca172.js"><link rel="prefetch" href="/blogs/assets/js/241.fc0fbb3a.js"><link rel="prefetch" href="/blogs/assets/js/242.121b560f.js"><link rel="prefetch" href="/blogs/assets/js/243.65bbc30d.js"><link rel="prefetch" href="/blogs/assets/js/244.4e1a4f6f.js"><link rel="prefetch" href="/blogs/assets/js/245.74650efa.js"><link rel="prefetch" href="/blogs/assets/js/246.44410da9.js"><link rel="prefetch" href="/blogs/assets/js/247.8b17ab29.js"><link rel="prefetch" href="/blogs/assets/js/248.bfd3427b.js"><link rel="prefetch" href="/blogs/assets/js/249.657d85b5.js"><link rel="prefetch" href="/blogs/assets/js/25.33d1b037.js"><link rel="prefetch" href="/blogs/assets/js/250.85d9364b.js"><link rel="prefetch" href="/blogs/assets/js/251.3a2731a1.js"><link rel="prefetch" href="/blogs/assets/js/252.614dddaa.js"><link rel="prefetch" href="/blogs/assets/js/253.e9644a72.js"><link rel="prefetch" href="/blogs/assets/js/254.91d89e86.js"><link rel="prefetch" href="/blogs/assets/js/255.3e45efd3.js"><link rel="prefetch" href="/blogs/assets/js/256.e3855631.js"><link rel="prefetch" href="/blogs/assets/js/257.c99ba8b4.js"><link rel="prefetch" href="/blogs/assets/js/258.d8b477e4.js"><link rel="prefetch" href="/blogs/assets/js/259.2ceb56a0.js"><link rel="prefetch" href="/blogs/assets/js/26.640d9a68.js"><link rel="prefetch" href="/blogs/assets/js/260.b4d81456.js"><link rel="prefetch" href="/blogs/assets/js/261.5f97ec93.js"><link rel="prefetch" href="/blogs/assets/js/262.65521c65.js"><link rel="prefetch" href="/blogs/assets/js/263.0b120aee.js"><link rel="prefetch" href="/blogs/assets/js/264.cb6dba1b.js"><link rel="prefetch" href="/blogs/assets/js/265.7a6b03f8.js"><link rel="prefetch" href="/blogs/assets/js/266.b5c6fa8d.js"><link rel="prefetch" href="/blogs/assets/js/267.be1a936e.js"><link rel="prefetch" href="/blogs/assets/js/268.1e24e2cc.js"><link rel="prefetch" href="/blogs/assets/js/269.0816f7a1.js"><link rel="prefetch" href="/blogs/assets/js/27.de6079ae.js"><link rel="prefetch" href="/blogs/assets/js/270.5d863231.js"><link rel="prefetch" href="/blogs/assets/js/271.6bf6c906.js"><link rel="prefetch" href="/blogs/assets/js/272.487d4e56.js"><link rel="prefetch" href="/blogs/assets/js/273.e851831e.js"><link rel="prefetch" href="/blogs/assets/js/274.ddfce773.js"><link rel="prefetch" href="/blogs/assets/js/275.7be6ccd7.js"><link rel="prefetch" href="/blogs/assets/js/276.e114860f.js"><link rel="prefetch" href="/blogs/assets/js/277.d426622a.js"><link rel="prefetch" href="/blogs/assets/js/278.065ed690.js"><link rel="prefetch" href="/blogs/assets/js/279.a97eb279.js"><link rel="prefetch" href="/blogs/assets/js/28.81d3531c.js"><link rel="prefetch" href="/blogs/assets/js/280.afca3fe3.js"><link rel="prefetch" href="/blogs/assets/js/281.e8afc801.js"><link rel="prefetch" href="/blogs/assets/js/282.6b369e76.js"><link rel="prefetch" href="/blogs/assets/js/283.b4e68cf0.js"><link rel="prefetch" href="/blogs/assets/js/284.4cc56fa2.js"><link rel="prefetch" href="/blogs/assets/js/285.37f3a771.js"><link rel="prefetch" href="/blogs/assets/js/286.eb75f6fc.js"><link rel="prefetch" href="/blogs/assets/js/287.5044aae8.js"><link rel="prefetch" href="/blogs/assets/js/288.3d6057f4.js"><link rel="prefetch" href="/blogs/assets/js/289.49f89a04.js"><link rel="prefetch" href="/blogs/assets/js/29.7978b908.js"><link rel="prefetch" href="/blogs/assets/js/290.3a24c2c7.js"><link rel="prefetch" href="/blogs/assets/js/291.a7a9f8d2.js"><link rel="prefetch" href="/blogs/assets/js/292.e6641495.js"><link rel="prefetch" href="/blogs/assets/js/293.69637ebc.js"><link rel="prefetch" href="/blogs/assets/js/294.34446dd9.js"><link rel="prefetch" href="/blogs/assets/js/295.e697cc4f.js"><link rel="prefetch" href="/blogs/assets/js/296.3a5217af.js"><link rel="prefetch" href="/blogs/assets/js/297.89f3f217.js"><link rel="prefetch" href="/blogs/assets/js/298.7d1e4493.js"><link rel="prefetch" href="/blogs/assets/js/299.dced7d34.js"><link rel="prefetch" href="/blogs/assets/js/3.469820f3.js"><link rel="prefetch" href="/blogs/assets/js/30.a3caea8a.js"><link rel="prefetch" href="/blogs/assets/js/300.c089a9a0.js"><link rel="prefetch" href="/blogs/assets/js/301.0a5a4fb3.js"><link rel="prefetch" href="/blogs/assets/js/302.24f71a08.js"><link rel="prefetch" href="/blogs/assets/js/303.e353ec2a.js"><link rel="prefetch" href="/blogs/assets/js/304.80727d70.js"><link rel="prefetch" href="/blogs/assets/js/305.5a5bc564.js"><link rel="prefetch" href="/blogs/assets/js/306.e7f9c236.js"><link rel="prefetch" href="/blogs/assets/js/307.08effa0e.js"><link rel="prefetch" href="/blogs/assets/js/308.4112802b.js"><link rel="prefetch" href="/blogs/assets/js/309.9571f2ca.js"><link rel="prefetch" href="/blogs/assets/js/31.5710f44b.js"><link rel="prefetch" href="/blogs/assets/js/310.5d368a48.js"><link rel="prefetch" href="/blogs/assets/js/311.16c11adf.js"><link rel="prefetch" href="/blogs/assets/js/312.db502820.js"><link rel="prefetch" href="/blogs/assets/js/313.325b6dba.js"><link rel="prefetch" href="/blogs/assets/js/314.16ea2951.js"><link rel="prefetch" href="/blogs/assets/js/315.6bb51af6.js"><link rel="prefetch" href="/blogs/assets/js/316.48dbfc7f.js"><link rel="prefetch" href="/blogs/assets/js/317.196398a0.js"><link rel="prefetch" href="/blogs/assets/js/318.4e8695f4.js"><link rel="prefetch" href="/blogs/assets/js/319.d5b8f8df.js"><link rel="prefetch" href="/blogs/assets/js/32.e12ad4a6.js"><link rel="prefetch" href="/blogs/assets/js/320.dbd4d64d.js"><link rel="prefetch" href="/blogs/assets/js/321.929a6292.js"><link rel="prefetch" href="/blogs/assets/js/322.0e3a130d.js"><link rel="prefetch" href="/blogs/assets/js/323.7d8c6df6.js"><link rel="prefetch" href="/blogs/assets/js/324.755c1e37.js"><link rel="prefetch" href="/blogs/assets/js/325.16d3b2aa.js"><link rel="prefetch" href="/blogs/assets/js/326.f9ea6d63.js"><link rel="prefetch" href="/blogs/assets/js/327.7aea27e4.js"><link rel="prefetch" href="/blogs/assets/js/328.4eea35b9.js"><link rel="prefetch" href="/blogs/assets/js/329.4f5ea131.js"><link rel="prefetch" href="/blogs/assets/js/33.15722ed9.js"><link rel="prefetch" href="/blogs/assets/js/330.5e79eb19.js"><link rel="prefetch" href="/blogs/assets/js/331.c73daf72.js"><link rel="prefetch" href="/blogs/assets/js/332.bf5b7eb2.js"><link rel="prefetch" href="/blogs/assets/js/333.bf517f24.js"><link rel="prefetch" href="/blogs/assets/js/334.2e504c7c.js"><link rel="prefetch" href="/blogs/assets/js/335.bbbe2c4d.js"><link rel="prefetch" href="/blogs/assets/js/336.4a98dd79.js"><link rel="prefetch" href="/blogs/assets/js/337.56b27c83.js"><link rel="prefetch" href="/blogs/assets/js/338.eeade5e8.js"><link rel="prefetch" href="/blogs/assets/js/339.057e28f8.js"><link rel="prefetch" href="/blogs/assets/js/34.eddf6f94.js"><link rel="prefetch" href="/blogs/assets/js/340.70ca722d.js"><link rel="prefetch" href="/blogs/assets/js/341.b83e3fc8.js"><link rel="prefetch" href="/blogs/assets/js/342.2276b167.js"><link rel="prefetch" href="/blogs/assets/js/343.ac09dccd.js"><link rel="prefetch" href="/blogs/assets/js/344.c80097fd.js"><link rel="prefetch" href="/blogs/assets/js/345.bb280ed6.js"><link rel="prefetch" href="/blogs/assets/js/346.5c1c9c8f.js"><link rel="prefetch" href="/blogs/assets/js/347.45f9adf8.js"><link rel="prefetch" href="/blogs/assets/js/348.55fa575c.js"><link rel="prefetch" href="/blogs/assets/js/349.14492112.js"><link rel="prefetch" href="/blogs/assets/js/35.2656429e.js"><link rel="prefetch" href="/blogs/assets/js/350.23760a3c.js"><link rel="prefetch" href="/blogs/assets/js/351.fbfa99b4.js"><link rel="prefetch" href="/blogs/assets/js/352.dd698868.js"><link rel="prefetch" href="/blogs/assets/js/353.40498626.js"><link rel="prefetch" href="/blogs/assets/js/354.588086f5.js"><link rel="prefetch" href="/blogs/assets/js/355.102fac11.js"><link rel="prefetch" href="/blogs/assets/js/356.cd1267bd.js"><link rel="prefetch" href="/blogs/assets/js/357.c65755fd.js"><link rel="prefetch" href="/blogs/assets/js/358.d415f76c.js"><link rel="prefetch" href="/blogs/assets/js/359.4530dbb7.js"><link rel="prefetch" href="/blogs/assets/js/36.07c0ff21.js"><link rel="prefetch" href="/blogs/assets/js/360.3f0f4e4c.js"><link rel="prefetch" href="/blogs/assets/js/361.850e34f5.js"><link rel="prefetch" href="/blogs/assets/js/362.a71e4238.js"><link rel="prefetch" href="/blogs/assets/js/363.f945f5ef.js"><link rel="prefetch" href="/blogs/assets/js/364.24e0c503.js"><link rel="prefetch" href="/blogs/assets/js/365.8312d12f.js"><link rel="prefetch" href="/blogs/assets/js/366.8d79aadc.js"><link rel="prefetch" href="/blogs/assets/js/367.80c580c9.js"><link rel="prefetch" href="/blogs/assets/js/368.767e89bb.js"><link rel="prefetch" href="/blogs/assets/js/369.455ee011.js"><link rel="prefetch" href="/blogs/assets/js/37.4a723830.js"><link rel="prefetch" href="/blogs/assets/js/370.77548a4b.js"><link rel="prefetch" href="/blogs/assets/js/371.fac90e21.js"><link rel="prefetch" href="/blogs/assets/js/372.5515dc63.js"><link rel="prefetch" href="/blogs/assets/js/373.50bec8c3.js"><link rel="prefetch" href="/blogs/assets/js/374.80fc0c40.js"><link rel="prefetch" href="/blogs/assets/js/375.5a1b8b5f.js"><link rel="prefetch" href="/blogs/assets/js/376.5f3782de.js"><link rel="prefetch" href="/blogs/assets/js/377.db20fdd4.js"><link rel="prefetch" href="/blogs/assets/js/378.c72b100b.js"><link rel="prefetch" href="/blogs/assets/js/379.d0c8d617.js"><link rel="prefetch" href="/blogs/assets/js/38.aa07c55d.js"><link rel="prefetch" href="/blogs/assets/js/380.7865f96f.js"><link rel="prefetch" href="/blogs/assets/js/381.6d80df08.js"><link rel="prefetch" href="/blogs/assets/js/382.054ff8d8.js"><link rel="prefetch" href="/blogs/assets/js/383.e4c6c136.js"><link rel="prefetch" href="/blogs/assets/js/384.301ca1c7.js"><link rel="prefetch" href="/blogs/assets/js/385.5511cf33.js"><link rel="prefetch" href="/blogs/assets/js/386.f9aa0fd5.js"><link rel="prefetch" href="/blogs/assets/js/387.5ae2eb60.js"><link rel="prefetch" href="/blogs/assets/js/388.1ecd0b93.js"><link rel="prefetch" href="/blogs/assets/js/389.e1585690.js"><link rel="prefetch" href="/blogs/assets/js/39.9d36a74f.js"><link rel="prefetch" href="/blogs/assets/js/390.2f1399c7.js"><link rel="prefetch" href="/blogs/assets/js/391.9b8b3ed6.js"><link rel="prefetch" href="/blogs/assets/js/392.0df64944.js"><link rel="prefetch" href="/blogs/assets/js/393.cd07056c.js"><link rel="prefetch" href="/blogs/assets/js/394.bfa9a9ff.js"><link rel="prefetch" href="/blogs/assets/js/395.0e837c6d.js"><link rel="prefetch" href="/blogs/assets/js/396.d0a581b4.js"><link rel="prefetch" href="/blogs/assets/js/397.da4377df.js"><link rel="prefetch" href="/blogs/assets/js/398.f71450a4.js"><link rel="prefetch" href="/blogs/assets/js/399.6284f2b9.js"><link rel="prefetch" href="/blogs/assets/js/4.b2084d38.js"><link rel="prefetch" href="/blogs/assets/js/40.2d10dee1.js"><link rel="prefetch" href="/blogs/assets/js/400.7040a50a.js"><link rel="prefetch" href="/blogs/assets/js/401.8bc0c0aa.js"><link rel="prefetch" href="/blogs/assets/js/402.013b720f.js"><link rel="prefetch" href="/blogs/assets/js/403.3e52abc2.js"><link rel="prefetch" href="/blogs/assets/js/404.d2cdd1ce.js"><link rel="prefetch" href="/blogs/assets/js/405.3e67b68c.js"><link rel="prefetch" href="/blogs/assets/js/406.79927ef5.js"><link rel="prefetch" href="/blogs/assets/js/407.b5ed71a7.js"><link rel="prefetch" href="/blogs/assets/js/408.145aa8f7.js"><link rel="prefetch" href="/blogs/assets/js/409.32610efe.js"><link rel="prefetch" href="/blogs/assets/js/41.21271d6a.js"><link rel="prefetch" href="/blogs/assets/js/410.4249dc3d.js"><link rel="prefetch" href="/blogs/assets/js/411.b31aa37d.js"><link rel="prefetch" href="/blogs/assets/js/412.03523ce7.js"><link rel="prefetch" href="/blogs/assets/js/413.e78807aa.js"><link rel="prefetch" href="/blogs/assets/js/414.a4a7aa8c.js"><link rel="prefetch" href="/blogs/assets/js/415.dfc662a7.js"><link rel="prefetch" href="/blogs/assets/js/416.d9ff6f56.js"><link rel="prefetch" href="/blogs/assets/js/417.c886ca90.js"><link rel="prefetch" href="/blogs/assets/js/418.58dbf064.js"><link rel="prefetch" href="/blogs/assets/js/419.21fbbd8f.js"><link rel="prefetch" href="/blogs/assets/js/42.2b169b47.js"><link rel="prefetch" href="/blogs/assets/js/420.692a166b.js"><link rel="prefetch" href="/blogs/assets/js/421.74f7624e.js"><link rel="prefetch" href="/blogs/assets/js/422.24b03dd4.js"><link rel="prefetch" href="/blogs/assets/js/423.84177236.js"><link rel="prefetch" href="/blogs/assets/js/424.a16c8c1f.js"><link rel="prefetch" href="/blogs/assets/js/425.e4790f48.js"><link rel="prefetch" href="/blogs/assets/js/426.76fb11ff.js"><link rel="prefetch" href="/blogs/assets/js/427.79f0988f.js"><link rel="prefetch" href="/blogs/assets/js/428.a7339a41.js"><link rel="prefetch" href="/blogs/assets/js/429.de6e129f.js"><link rel="prefetch" href="/blogs/assets/js/43.c565f1af.js"><link rel="prefetch" href="/blogs/assets/js/430.7fea3f78.js"><link rel="prefetch" href="/blogs/assets/js/431.dcc6f607.js"><link rel="prefetch" href="/blogs/assets/js/432.212162e9.js"><link rel="prefetch" href="/blogs/assets/js/433.f776b91d.js"><link rel="prefetch" href="/blogs/assets/js/434.3b707b56.js"><link rel="prefetch" href="/blogs/assets/js/435.b7aa4aee.js"><link rel="prefetch" href="/blogs/assets/js/436.80d22e5a.js"><link rel="prefetch" href="/blogs/assets/js/437.3053916e.js"><link rel="prefetch" href="/blogs/assets/js/438.35a1eb12.js"><link rel="prefetch" href="/blogs/assets/js/439.e1a159ba.js"><link rel="prefetch" href="/blogs/assets/js/44.162eb5da.js"><link rel="prefetch" href="/blogs/assets/js/440.eed32138.js"><link rel="prefetch" href="/blogs/assets/js/441.eac95432.js"><link rel="prefetch" href="/blogs/assets/js/442.4712abf5.js"><link rel="prefetch" href="/blogs/assets/js/443.4b5aaf02.js"><link rel="prefetch" href="/blogs/assets/js/444.909b694f.js"><link rel="prefetch" href="/blogs/assets/js/445.6a709980.js"><link rel="prefetch" href="/blogs/assets/js/446.e7b5d143.js"><link rel="prefetch" href="/blogs/assets/js/447.c2adf354.js"><link rel="prefetch" href="/blogs/assets/js/448.bc3639d5.js"><link rel="prefetch" href="/blogs/assets/js/449.de0efc63.js"><link rel="prefetch" href="/blogs/assets/js/45.273542f9.js"><link rel="prefetch" href="/blogs/assets/js/450.352c7201.js"><link rel="prefetch" href="/blogs/assets/js/451.548a0e77.js"><link rel="prefetch" href="/blogs/assets/js/452.cefaa4e7.js"><link rel="prefetch" href="/blogs/assets/js/453.699cb6b8.js"><link rel="prefetch" href="/blogs/assets/js/454.b7f7f39b.js"><link rel="prefetch" href="/blogs/assets/js/455.0aa0d132.js"><link rel="prefetch" href="/blogs/assets/js/456.752f987c.js"><link rel="prefetch" href="/blogs/assets/js/457.f2c21cb0.js"><link rel="prefetch" href="/blogs/assets/js/458.0fccfa1a.js"><link rel="prefetch" href="/blogs/assets/js/459.2b77e495.js"><link rel="prefetch" href="/blogs/assets/js/46.936a08c3.js"><link rel="prefetch" href="/blogs/assets/js/460.cc655724.js"><link rel="prefetch" href="/blogs/assets/js/461.5c9c96b2.js"><link rel="prefetch" href="/blogs/assets/js/462.12641aca.js"><link rel="prefetch" href="/blogs/assets/js/463.e9e3ea74.js"><link rel="prefetch" href="/blogs/assets/js/464.31126ee5.js"><link rel="prefetch" href="/blogs/assets/js/465.990c468c.js"><link rel="prefetch" href="/blogs/assets/js/466.958f9a54.js"><link rel="prefetch" href="/blogs/assets/js/467.228041f6.js"><link rel="prefetch" href="/blogs/assets/js/468.2fa13ad9.js"><link rel="prefetch" href="/blogs/assets/js/469.74b7d516.js"><link rel="prefetch" href="/blogs/assets/js/47.fc5aaa97.js"><link rel="prefetch" href="/blogs/assets/js/470.9c6ddcde.js"><link rel="prefetch" href="/blogs/assets/js/471.a68eabb2.js"><link rel="prefetch" href="/blogs/assets/js/472.98129924.js"><link rel="prefetch" href="/blogs/assets/js/473.17794672.js"><link rel="prefetch" href="/blogs/assets/js/474.2995095f.js"><link rel="prefetch" href="/blogs/assets/js/475.64f80f36.js"><link rel="prefetch" href="/blogs/assets/js/48.895827c2.js"><link rel="prefetch" href="/blogs/assets/js/49.2cecf465.js"><link rel="prefetch" href="/blogs/assets/js/5.d7bbd3d9.js"><link rel="prefetch" href="/blogs/assets/js/50.2972ddee.js"><link rel="prefetch" href="/blogs/assets/js/51.eab84d6d.js"><link rel="prefetch" href="/blogs/assets/js/52.8a915401.js"><link rel="prefetch" href="/blogs/assets/js/53.8eabe307.js"><link rel="prefetch" href="/blogs/assets/js/54.dd0207a2.js"><link rel="prefetch" href="/blogs/assets/js/55.9071c1f8.js"><link rel="prefetch" href="/blogs/assets/js/56.abf569a1.js"><link rel="prefetch" href="/blogs/assets/js/57.55b7a067.js"><link rel="prefetch" href="/blogs/assets/js/58.41f9b620.js"><link rel="prefetch" href="/blogs/assets/js/59.6ebf6261.js"><link rel="prefetch" href="/blogs/assets/js/6.ee65c1e7.js"><link rel="prefetch" href="/blogs/assets/js/60.869205cc.js"><link rel="prefetch" href="/blogs/assets/js/61.2cb25722.js"><link rel="prefetch" href="/blogs/assets/js/62.07a76d23.js"><link rel="prefetch" href="/blogs/assets/js/63.06b6fdce.js"><link rel="prefetch" href="/blogs/assets/js/64.6d213f4c.js"><link rel="prefetch" href="/blogs/assets/js/65.205a4511.js"><link rel="prefetch" href="/blogs/assets/js/66.aaaffa89.js"><link rel="prefetch" href="/blogs/assets/js/67.1d6a2e56.js"><link rel="prefetch" href="/blogs/assets/js/68.3a3a1937.js"><link rel="prefetch" href="/blogs/assets/js/69.233e765f.js"><link rel="prefetch" href="/blogs/assets/js/7.95c5731c.js"><link rel="prefetch" href="/blogs/assets/js/70.581b4adb.js"><link rel="prefetch" href="/blogs/assets/js/71.c5412492.js"><link rel="prefetch" href="/blogs/assets/js/72.20ef83ef.js"><link rel="prefetch" href="/blogs/assets/js/73.2bb1c525.js"><link rel="prefetch" href="/blogs/assets/js/74.1516c569.js"><link rel="prefetch" href="/blogs/assets/js/75.c3370786.js"><link rel="prefetch" href="/blogs/assets/js/76.80e4fe0c.js"><link rel="prefetch" href="/blogs/assets/js/77.f2c7adac.js"><link rel="prefetch" href="/blogs/assets/js/78.8e806f46.js"><link rel="prefetch" href="/blogs/assets/js/79.18d03739.js"><link rel="prefetch" href="/blogs/assets/js/8.6c8082e2.js"><link rel="prefetch" href="/blogs/assets/js/80.a65a8759.js"><link rel="prefetch" href="/blogs/assets/js/81.d8a5fbe0.js"><link rel="prefetch" href="/blogs/assets/js/82.c642a64d.js"><link rel="prefetch" href="/blogs/assets/js/83.33fa18d7.js"><link rel="prefetch" href="/blogs/assets/js/84.f6edf7b8.js"><link rel="prefetch" href="/blogs/assets/js/85.b2751517.js"><link rel="prefetch" href="/blogs/assets/js/86.3c361927.js"><link rel="prefetch" href="/blogs/assets/js/87.1af5df70.js"><link rel="prefetch" href="/blogs/assets/js/88.ec0bd5de.js"><link rel="prefetch" href="/blogs/assets/js/89.aa8e0f1e.js"><link rel="prefetch" href="/blogs/assets/js/9.b33bc7c6.js"><link rel="prefetch" href="/blogs/assets/js/90.dba5a8d2.js"><link rel="prefetch" href="/blogs/assets/js/91.fb84fe0a.js"><link rel="prefetch" href="/blogs/assets/js/92.92e6527e.js"><link rel="prefetch" href="/blogs/assets/js/93.a9cede4e.js"><link rel="prefetch" href="/blogs/assets/js/94.e2e01b5e.js"><link rel="prefetch" href="/blogs/assets/js/95.5ca324a4.js"><link rel="prefetch" href="/blogs/assets/js/96.d70070fb.js"><link rel="prefetch" href="/blogs/assets/js/97.84d7ab42.js"><link rel="prefetch" href="/blogs/assets/js/98.a33985b1.js"><link rel="prefetch" href="/blogs/assets/js/99.bbe78d52.js">
    <link rel="stylesheet" href="/blogs/assets/css/0.styles.7a0dfb7e.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container have-rightmenu" data-v-f848d4e8><div class="global-loading-wrapper" data-v-3a334c6d data-v-f848d4e8 data-v-f848d4e8><div class="loader-main" data-v-3a334c6d><img src="/blogs/assets/img/loading.a592e2e5.jpg" alt="loading" data-v-3a334c6d></div></div> <div class="hide" data-v-f848d4e8><header class="navbar" data-v-f848d4e8><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/blogs/" class="home-link router-link-active"><img src="/blogs/img/kmc.jpg" alt="卡夫卡的岛上书店" class="logo"> <span class="site-name">卡夫卡的岛上书店</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">选择模式</h4> <ul class="color-mode-options"><li class="dark">深色模式</li><li class="light active">浅色模式</li><li class="read">阅读模式</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <ul class="suggestions" style="display:none;"></ul></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/blogs/" class="nav-link"><i class="iconfont reco-home"></i>首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/web/" class="nav-link"><i></i>前端
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>文档教程</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/web/docs/imooc/wiki/" class="nav-link"><i class="iconfont reco-blog"></i>慕课教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/es6/" class="nav-link"><i class="iconfont reco-blog"></i>ES6 入门教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/wangdoc/javascript/" class="nav-link"><i class="iconfont reco-blog"></i>网道-JavaScript 教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/angular/" class="nav-link"><i class="iconfont reco-blog"></i>Angular 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/react/" class="nav-link"><i class="iconfont reco-blog"></i>React 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/vue/" class="nav-link"><i class="iconfont reco-blog"></i>Vue 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/node/" class="nav-link"><i class="iconfont reco-blog"></i>Node 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/babel/" class="nav-link"><i class="iconfont reco-blog"></i>Babel 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/webpack/" class="nav-link"><i class="iconfont reco-blog"></i>Webpack 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/typescript/" class="nav-link"><i class="iconfont reco-blog"></i>TypeScript 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/runoob/" class="nav-link"><i class="iconfont reco-blog"></i>菜鸟教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/docschina/" class="nav-link"><i class="iconfont reco-blog"></i>印记中文
</a></li></ul></li><li class="dropdown-item"><h4>专栏笔记</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/column-notes/33-js/" class="nav-link"><i class="iconfont reco-blog"></i>JavaScript的33个概念
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/relearn-frontend/" class="nav-link"><i class="iconfont reco-blog"></i>重学前端
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/http-protocol/" class="nav-link"><i class="iconfont reco-blog"></i>透视HTTP协议
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/play-webpack/" class="nav-link"><i class="iconfont reco-blog"></i>玩转webpack
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/browser-principle/" class="nav-link"><i class="iconfont reco-blog"></i>浏览器工作原理与实践
</a></li></ul></li><li class="dropdown-item"><h4>书籍笔记</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/book-notes/donot-know-javascript/" class="nav-link"><i class="iconfont reco-blog"></i>你不知道的JavaScript
</a></li></ul></li><li class="dropdown-item"><h4>推荐博客</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/web/ruanyifeng/" class="nav-link"><i class="iconfont reco-blog"></i>阮一峰的个人网站
</a></li><li class="dropdown-subitem"><a href="/blogs/web/liaoxuefeng/" class="nav-link"><i class="iconfont reco-blog"></i>廖雪峰的官方网站
</a></li></ul></li><li class="dropdown-item"><h4>工具</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/web/tools/astexplorer/" class="nav-link"><i class="iconfont reco-blog"></i>AST Explorer
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/golang/" class="nav-link router-link-active"><i></i>Golang
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>文档资源</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/golang/docs/gopl-zh/" class="nav-link"><i class="iconfont reco-blog"></i>Go语言圣经（中文版）
</a></li><li class="dropdown-subitem"><a href="/blogs/golang/docs/31de972b403fd/" class="nav-link"><i class="iconfont reco-blog"></i>Go 语言学习资料
</a></li></ul></li><li class="dropdown-item"><h4>书籍笔记</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/golang/book-notes/the-way-to-go/" class="nav-link router-link-active"><i class="iconfont reco-blog"></i>Go入门指南
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/library/" class="nav-link"><i></i>图书馆
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>太易</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/map/" class="nav-link"><i class="iconfont reco-blog"></i>时间地图
</a></li></ul></li><li class="dropdown-item"><h4>太初</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/wiki/" class="nav-link"><i class="iconfont reco-blog"></i>中文维基百科
</a></li></ul></li><li class="dropdown-item"><h4>太始</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/wdl/" class="nav-link"><i class="iconfont reco-blog"></i>世界数字图书馆
</a></li></ul></li><li class="dropdown-item"><h4>太素</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/douban/" class="nav-link"><i class="iconfont reco-blog"></i>豆瓣榜单
</a></li><li class="dropdown-subitem"><a href="/blogs/library/open163/" class="nav-link"><i class="iconfont reco-blog"></i>网易公开课
</a></li></ul></li><li class="dropdown-item"><h4>太极</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/shici/" class="nav-link"><i class="iconfont reco-blog"></i>中华诗词
</a></li><li class="dropdown-subitem"><a href="/blogs/library/processon/" class="nav-link"><i class="iconfont reco-blog"></i>ProcessOn图形化知识资源
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/idealism/" class="nav-link"><i></i>昨日与明日
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>昨日</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/idealism/music/" class="nav-link"><i class="iconfont reco-blog"></i>音乐
</a></li></ul></li><li class="dropdown-item"><h4>今日</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/idealism/philosophy/" class="nav-link"><i class="iconfont reco-blog"></i>哲学
</a></li></ul></li><li class="dropdown-item"><h4>明日</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/idealism/kaimo/" class="nav-link"><i class="iconfont reco-blog"></i>忧伤的年轻人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-api"></i>索引
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blogs/sitemap/" class="nav-link"><i class="iconfont reco-blog"></i>总目录
</a></li><li class="dropdown-item"><!----> <a href="/blogs/categories/" class="nav-link"><i class="iconfont reco-category"></i>分类
</a></li><li class="dropdown-item"><!----> <a href="/blogs/tags/" class="nav-link"><i class="iconfont reco-tag"></i>标签
</a></li><li class="dropdown-item"><!----> <a href="/blogs/archives/" class="nav-link"><i class="iconfont reco-date"></i>归档
</a></li></ul></div></div><div class="nav-item"><a href="/blogs/bookshop/message-board/" class="nav-link"><i class="iconfont reco-suggestion"></i>留言板
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-message"></i>关于
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>联系</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://blog.csdn.net/kaimo313" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-csdn"></i>CSDN
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://gitee.com/kaimo313" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-mayun"></i>Gitee
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://github.com/kaimo313" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-github"></i>GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="/blogs/bookshop/linkme/" class="nav-link"><i class="iconfont reco-account"></i>联系店长
</a></li></ul></li><li class="dropdown-item"><h4>博客</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/bookshop/explain/" class="nav-link"><i class="iconfont reco-document"></i>博客说明
</a></li><li class="dropdown-subitem"><a href="/blogs/bookshop/logs/" class="nav-link"><i class="iconfont reco-document"></i>更新日志
</a></li></ul></li><li class="dropdown-item"><h4>其他</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/resource-tools/" class="nav-link"><i class="iconfont reco-document"></i>资源工具
</a></li><li class="dropdown-subitem"><a href="/blogs/bookshop/friendslink/" class="nav-link"><i class="iconfont reco-friend"></i>友情链接
</a></li></ul></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask" data-v-f848d4e8></div> <aside class="sidebar" data-v-f848d4e8><div class="personal-info-wrapper" data-v-34faaed8 data-v-f848d4e8><img src="/blogs/img/avatar.jpg" alt="author-avatar" class="personal-img" data-v-34faaed8> <div class="author" data-v-34faaed8>
    凯小默
  </div> <div class="personal-info-details" data-v-34faaed8><div data-v-34faaed8>文章：<span data-v-34faaed8>404</span></div> <div data-v-34faaed8>地点：<span data-v-34faaed8>canton</span></div></div> <div class="slogan" data-v-34faaed8>
    standing on the shoulders of giants
  </div> <ul class="social-links" data-v-34faaed8><li class="social-item" data-v-34faaed8><i class="iconfont reco-csdn" style="color:#fc5531;" data-v-34faaed8></i></li><li class="social-item" data-v-34faaed8><i class="iconfont reco-mayun" style="color:#c71d24;" data-v-34faaed8></i></li><li class="social-item" data-v-34faaed8><i class="iconfont reco-bilibili" style="color:#fb7299;" data-v-34faaed8></i></li><li class="social-item" data-v-34faaed8><i class="iconfont reco-github" style="color:#3eaf7c;" data-v-34faaed8></i></li><li class="social-item" data-v-34faaed8><i class="iconfont reco-mail" style="color:#00a1d6;" data-v-34faaed8></i></li></ul></div> <nav class="nav-links"><div class="nav-item"><a href="/blogs/" class="nav-link"><i class="iconfont reco-home"></i>首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/web/" class="nav-link"><i></i>前端
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>文档教程</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/web/docs/imooc/wiki/" class="nav-link"><i class="iconfont reco-blog"></i>慕课教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/es6/" class="nav-link"><i class="iconfont reco-blog"></i>ES6 入门教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/wangdoc/javascript/" class="nav-link"><i class="iconfont reco-blog"></i>网道-JavaScript 教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/angular/" class="nav-link"><i class="iconfont reco-blog"></i>Angular 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/react/" class="nav-link"><i class="iconfont reco-blog"></i>React 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/vue/" class="nav-link"><i class="iconfont reco-blog"></i>Vue 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/node/" class="nav-link"><i class="iconfont reco-blog"></i>Node 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/babel/" class="nav-link"><i class="iconfont reco-blog"></i>Babel 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/webpack/" class="nav-link"><i class="iconfont reco-blog"></i>Webpack 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/typescript/" class="nav-link"><i class="iconfont reco-blog"></i>TypeScript 文档
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/runoob/" class="nav-link"><i class="iconfont reco-blog"></i>菜鸟教程
</a></li><li class="dropdown-subitem"><a href="/blogs/web/docs/docschina/" class="nav-link"><i class="iconfont reco-blog"></i>印记中文
</a></li></ul></li><li class="dropdown-item"><h4>专栏笔记</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/column-notes/33-js/" class="nav-link"><i class="iconfont reco-blog"></i>JavaScript的33个概念
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/relearn-frontend/" class="nav-link"><i class="iconfont reco-blog"></i>重学前端
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/http-protocol/" class="nav-link"><i class="iconfont reco-blog"></i>透视HTTP协议
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/play-webpack/" class="nav-link"><i class="iconfont reco-blog"></i>玩转webpack
</a></li><li class="dropdown-subitem"><a href="/blogs/column-notes/browser-principle/" class="nav-link"><i class="iconfont reco-blog"></i>浏览器工作原理与实践
</a></li></ul></li><li class="dropdown-item"><h4>书籍笔记</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/book-notes/donot-know-javascript/" class="nav-link"><i class="iconfont reco-blog"></i>你不知道的JavaScript
</a></li></ul></li><li class="dropdown-item"><h4>推荐博客</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/web/ruanyifeng/" class="nav-link"><i class="iconfont reco-blog"></i>阮一峰的个人网站
</a></li><li class="dropdown-subitem"><a href="/blogs/web/liaoxuefeng/" class="nav-link"><i class="iconfont reco-blog"></i>廖雪峰的官方网站
</a></li></ul></li><li class="dropdown-item"><h4>工具</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/web/tools/astexplorer/" class="nav-link"><i class="iconfont reco-blog"></i>AST Explorer
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/golang/" class="nav-link router-link-active"><i></i>Golang
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>文档资源</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/golang/docs/gopl-zh/" class="nav-link"><i class="iconfont reco-blog"></i>Go语言圣经（中文版）
</a></li><li class="dropdown-subitem"><a href="/blogs/golang/docs/31de972b403fd/" class="nav-link"><i class="iconfont reco-blog"></i>Go 语言学习资料
</a></li></ul></li><li class="dropdown-item"><h4>书籍笔记</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/golang/book-notes/the-way-to-go/" class="nav-link router-link-active"><i class="iconfont reco-blog"></i>Go入门指南
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/library/" class="nav-link"><i></i>图书馆
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>太易</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/map/" class="nav-link"><i class="iconfont reco-blog"></i>时间地图
</a></li></ul></li><li class="dropdown-item"><h4>太初</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/wiki/" class="nav-link"><i class="iconfont reco-blog"></i>中文维基百科
</a></li></ul></li><li class="dropdown-item"><h4>太始</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/wdl/" class="nav-link"><i class="iconfont reco-blog"></i>世界数字图书馆
</a></li></ul></li><li class="dropdown-item"><h4>太素</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/douban/" class="nav-link"><i class="iconfont reco-blog"></i>豆瓣榜单
</a></li><li class="dropdown-subitem"><a href="/blogs/library/open163/" class="nav-link"><i class="iconfont reco-blog"></i>网易公开课
</a></li></ul></li><li class="dropdown-item"><h4>太极</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/library/shici/" class="nav-link"><i class="iconfont reco-blog"></i>中华诗词
</a></li><li class="dropdown-subitem"><a href="/blogs/library/processon/" class="nav-link"><i class="iconfont reco-blog"></i>ProcessOn图形化知识资源
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><a href="/blogs/idealism/" class="nav-link"><i></i>昨日与明日
      </a></span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>昨日</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/idealism/music/" class="nav-link"><i class="iconfont reco-blog"></i>音乐
</a></li></ul></li><li class="dropdown-item"><h4>今日</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/idealism/philosophy/" class="nav-link"><i class="iconfont reco-blog"></i>哲学
</a></li></ul></li><li class="dropdown-item"><h4>明日</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/idealism/kaimo/" class="nav-link"><i class="iconfont reco-blog"></i>忧伤的年轻人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-api"></i>索引
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blogs/sitemap/" class="nav-link"><i class="iconfont reco-blog"></i>总目录
</a></li><li class="dropdown-item"><!----> <a href="/blogs/categories/" class="nav-link"><i class="iconfont reco-category"></i>分类
</a></li><li class="dropdown-item"><!----> <a href="/blogs/tags/" class="nav-link"><i class="iconfont reco-tag"></i>标签
</a></li><li class="dropdown-item"><!----> <a href="/blogs/archives/" class="nav-link"><i class="iconfont reco-date"></i>归档
</a></li></ul></div></div><div class="nav-item"><a href="/blogs/bookshop/message-board/" class="nav-link"><i class="iconfont reco-suggestion"></i>留言板
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-message"></i>关于
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>联系</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://blog.csdn.net/kaimo313" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-csdn"></i>CSDN
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://gitee.com/kaimo313" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-mayun"></i>Gitee
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://github.com/kaimo313" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-github"></i>GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="/blogs/bookshop/linkme/" class="nav-link"><i class="iconfont reco-account"></i>联系店长
</a></li></ul></li><li class="dropdown-item"><h4>博客</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/bookshop/explain/" class="nav-link"><i class="iconfont reco-document"></i>博客说明
</a></li><li class="dropdown-subitem"><a href="/blogs/bookshop/logs/" class="nav-link"><i class="iconfont reco-document"></i>更新日志
</a></li></ul></li><li class="dropdown-item"><h4>其他</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/blogs/resource-tools/" class="nav-link"><i class="iconfont reco-document"></i>资源工具
</a></li><li class="dropdown-subitem"><a href="/blogs/bookshop/friendslink/" class="nav-link"><i class="iconfont reco-friend"></i>友情链接
</a></li></ul></li></ul></div></div> <!----></nav> <ul class="sidebar-links"><li><a href="/blogs/golang/book-notes/the-way-to-go/af321cdfef51/" class="sidebar-link">前言</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>第一部分：学习 Go 语言</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>第二部分：语言的核心结构与技术</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>第三部分：Go 高级编程</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>第四部分：实际应用</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <div><main class="page"><div class="theme-vdoing-wrapper bg-style-14"><div class="articleInfo-wrap" data-v-13f19dad><div class="articleInfo" data-v-13f19dad><ul class="breadcrumbs" data-v-13f19dad><li data-v-13f19dad><a href="/blogs/" title="首页" class="fa fa-laptop-house router-link-active" data-v-13f19dad></a></li> <li data-v-13f19dad><a href="/blogs/golang/book-notes/the-way-to-go/" title="Go入门指南-目录页" class="router-link-active" data-v-13f19dad>Go入门指南</a></li> <li data-v-13f19dad><a href="/blogs/golang/book-notes/the-way-to-go/#第二部分：语言的核心结构与技术" title="Go入门指南#第二部分：语言的核心结构与技术" data-v-13f19dad>第二部分：语言的核心结构与技术</a></li> <li data-v-13f19dad><a href="/blogs/golang/book-notes/the-way-to-go/#第10章：结构（struct）与方法（method）" title="Go入门指南#第10章：结构（struct）与方法（method）" data-v-13f19dad>第10章：结构（struct）与方法（method）</a></li></ul> <div class="info" data-v-13f19dad><div title="作者" class="author fa fa-user" data-v-13f19dad><a href="https://github.com/unknwon/" target="_blank" title="作者" class="beLink" data-v-13f19dad>unknwon</a></div> <div title="创建时间" class="date fa fa-calendar-alt" data-v-13f19dad><a href="javascript:;" data-v-13f19dad>2021/03/05 16:40:32</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-content"></div></div></div> <h1><img src="">
            方法
          </h1> <div class="theme-vdoing-content content__default"><h2 id="_10-6-1-方法是什么"><a href="#_10-6-1-方法是什么" class="header-anchor">#</a> 10.6.1 方法是什么</h2> <p>在 Go 语言中，结构体就像是类的一种简化形式，那么面向对象程序员可能会问：类的方法在哪里呢？在 Go 中有一个概念，它和方法有着同样的名字，并且大体上意思相同：Go 方法是作用在接收者（receiver）上的一个函数，接收者是某种类型的变量。因此方法是一种特殊类型的函数。</p> <p>接收者类型可以是（几乎）任何类型，不仅仅是结构体类型：任何类型都可以有方法，甚至可以是函数类型，可以是 int、bool、string 或数组的别名类型。但是接收者不能是一个接口类型（参考 第 11 章），因为接口是一个抽象定义，但是方法却是具体实现；如果这样做会引发一个编译错误：<strong>invalid receiver type…</strong>。</p> <p>最后接收者不能是一个指针类型，但是它可以是任何其他允许类型的指针。</p> <p>一个类型加上它的方法等价于面向对象中的一个类。一个重要的区别是：在 Go 中，类型的代码和绑定在它上面的方法的代码可以不放置在一起，它们可以存在在不同的源文件，唯一的要求是：它们必须是同一个包的。</p> <p>类型 T（或 *T）上的所有方法的集合叫做类型 T（或 *T）的方法集（method set）。</p> <p>因为方法是函数，所以同样的，不允许方法重载，即对于一个类型只能有一个给定名称的方法。但是如果基于接收者类型，是有重载的：具有同样名字的方法可以在 2 个或多个不同的接收者类型上存在，比如在同一个包里这么做是允许的：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>denseMatrix<span class="token punctuation">)</span> <span class="token function">Add</span><span class="token punctuation">(</span>b Matrix<span class="token punctuation">)</span> Matrix
<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>sparseMatrix<span class="token punctuation">)</span> <span class="token function">Add</span><span class="token punctuation">(</span>b Matrix<span class="token punctuation">)</span> Matrix
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>别名类型没有原始类型上已经定义过的方法。</p> <p>定义方法的一般格式如下：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>recv receiver_type<span class="token punctuation">)</span> <span class="token function">methodName</span><span class="token punctuation">(</span>parameter_list<span class="token punctuation">)</span> <span class="token punctuation">(</span>return_value_list<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>在方法名之前，<code>func</code> 关键字之后的括号中指定 receiver。</p> <p>如果 <code>recv</code> 是 receiver 的实例，Method1 是它的方法名，那么方法调用遵循传统的 <code>object.name</code> 选择器符号：<strong>recv.Method1()</strong>。</p> <p>如果 <code>recv</code> 是一个指针，Go 会自动解引用。</p> <p>如果方法不需要使用 <code>recv</code> 的值，可以用 <strong>_</strong> 替换它，比如：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token boolean">_</span> receiver_type<span class="token punctuation">)</span> <span class="token function">methodName</span><span class="token punctuation">(</span>parameter_list<span class="token punctuation">)</span> <span class="token punctuation">(</span>return_value_list<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><code>recv</code> 就像是面向对象语言中的 <code>this</code> 或 <code>self</code>，但是 Go 中并没有这两个关键字。随个人喜好，你可以使用 <code>this</code> 或 <code>self</code> 作为 receiver 的名字。下面是一个结构体上的简单方法的例子：</p> <p>示例 10.10 method .go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token string">&quot;fmt&quot;</span>

<span class="token keyword">type</span> TwoInts <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	a <span class="token builtin">int</span>
	b <span class="token builtin">int</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	two1 <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>TwoInts<span class="token punctuation">)</span>
	two1<span class="token punctuation">.</span>a <span class="token operator">=</span> <span class="token number">12</span>
	two1<span class="token punctuation">.</span>b <span class="token operator">=</span> <span class="token number">10</span>

	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;The sum is: %d\n&quot;</span><span class="token punctuation">,</span> two1<span class="token punctuation">.</span><span class="token function">AddThem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;Add them to the param: %d\n&quot;</span><span class="token punctuation">,</span> two1<span class="token punctuation">.</span><span class="token function">AddToParam</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

	two2 <span class="token operator">:=</span> TwoInts<span class="token punctuation">{</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span>
	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;The sum is: %d\n&quot;</span><span class="token punctuation">,</span> two2<span class="token punctuation">.</span><span class="token function">AddThem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>tn <span class="token operator">*</span>TwoInts<span class="token punctuation">)</span> <span class="token function">AddThem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> tn<span class="token punctuation">.</span>a <span class="token operator">+</span> tn<span class="token punctuation">.</span>b
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>tn <span class="token operator">*</span>TwoInts<span class="token punctuation">)</span> <span class="token function">AddToParam</span><span class="token punctuation">(</span>param <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> tn<span class="token punctuation">.</span>a <span class="token operator">+</span> tn<span class="token punctuation">.</span>b <span class="token operator">+</span> param
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div><p>输出：</p> <div class="language- extra-class"><pre><code>The sum is: 22
Add them to the param: 42
The sum is: 7
</code></pre></div><p>下面是非结构体类型上方法的例子：</p> <p>示例 10.11 method2.go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token string">&quot;fmt&quot;</span>

<span class="token keyword">type</span> IntVector <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>v IntVector<span class="token punctuation">)</span> <span class="token function">Sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>s <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> x <span class="token operator">:=</span> <span class="token keyword">range</span> v <span class="token punctuation">{</span>
		s <span class="token operator">+=</span> x
	<span class="token punctuation">}</span>
	<span class="token keyword">return</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>IntVector<span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">Sum</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 输出是6</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p><strong>练习 10.6</strong> employee_salary.go</p> <p>定义结构体 <code>employee</code>，它有一个 <code>salary</code> 字段，给这个结构体定义一个方法 <code>giveRaise</code> 来按照指定的百分比增加薪水。</p> <p><strong>练习 10.7</strong> iteration_list.go</p> <p>下面这段代码有什么错？</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token string">&quot;container/list&quot;</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>p <span class="token operator">*</span>list<span class="token punctuation">.</span>List<span class="token punctuation">)</span> <span class="token function">Iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// ...</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	lst <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>list<span class="token punctuation">.</span>List<span class="token punctuation">)</span>
	<span class="token keyword">for</span> <span class="token boolean">_</span><span class="token operator">=</span> <span class="token keyword">range</span> lst<span class="token punctuation">.</span><span class="token function">Iter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>类型和作用在它上面定义的方法必须在同一个包里定义，这就是为什么不能在 int、float 或类似这些的类型上定义方法。试图在 int 类型上定义方法会得到一个编译错误：</p> <div class="language- extra-class"><pre><code>cannot define new methods on non-local type int
</code></pre></div><p>比如想在 <code>time.Time</code> 上定义如下方法：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>t time<span class="token punctuation">.</span>Time<span class="token punctuation">)</span> <span class="token function">first3Chars</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> time<span class="token punctuation">.</span><span class="token function">LocalTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>类型在其他的，或是非本地的包里定义，在它上面定义方法都会得到和上面同样的错误。</p> <p>但是有一个间接的方式：可以先定义该类型（比如：int 或 float）的别名类型，然后再为别名类型定义方法。或者像下面这样将它作为匿名类型嵌入在一个新的结构体中。当然方法只在这个别名类型上有效。</p> <p>示例 10.12 method_on_time.go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
	<span class="token string">&quot;time&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> myTime <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	time<span class="token punctuation">.</span>Time <span class="token comment">//anonymous field</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>t myTime<span class="token punctuation">)</span> <span class="token function">first3Chars</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> t<span class="token punctuation">.</span>Time<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	m <span class="token operator">:=</span> myTime<span class="token punctuation">{</span>time<span class="token punctuation">.</span><span class="token function">Now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">}</span>
	<span class="token comment">// 调用匿名Time上的String方法</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;Full time now:&quot;</span><span class="token punctuation">,</span> m<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
	<span class="token comment">// 调用myTime.first3Chars</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;First 3 chars:&quot;</span><span class="token punctuation">,</span> m<span class="token punctuation">.</span><span class="token function">first3Chars</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">/* Output:
Full time now: Mon Oct 24 15:34:54 Romance Daylight Time 2011
First 3 chars: Mon
*/</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><h2 id="_10-6-2-函数和方法的区别"><a href="#_10-6-2-函数和方法的区别" class="header-anchor">#</a> 10.6.2 函数和方法的区别</h2> <p>函数将变量作为参数：<strong>Function1(recv)</strong></p> <p>方法在变量上被调用：<strong>recv.Method1()</strong></p> <p>在接收者是指针时，方法可以改变接收者的值（或状态），这点函数也可以做到（当参数作为指针传递，即通过引用调用时，函数也可以改变参数的状态）。</p> <p><strong>不要忘记 Method1 后边的括号 ()，否则会引发编译器错误：<code>method recv.Method1 is not an expression, must be called</code></strong></p> <p>接收者必须有一个显式的名字，这个名字必须在方法中被使用。</p> <p><strong>receiver_type</strong> 叫做 <strong>（接收者）基本类型</strong>，这个类型必须在和方法同样的包中被声明。</p> <p>在 Go 中，（接收者）类型关联的方法不写在类型结构里面，就像类那样；耦合更加宽松；类型和方法之间的关联由接收者来建立。</p> <p><strong>方法没有和数据定义（结构体）混在一起：它们是正交的类型；表示（数据）和行为（方法）是独立的。</strong></p> <h2 id="_10-6-3-指针或值作为接收者"><a href="#_10-6-3-指针或值作为接收者" class="header-anchor">#</a> 10.6.3 指针或值作为接收者</h2> <p>鉴于性能的原因，<code>recv</code> 最常见的是一个指向 receiver_type 的指针（因为我们不想要一个实例的拷贝，如果按值调用的话就会是这样），特别是在 receiver 类型是结构体时，就更是如此了。</p> <p>如果想要方法改变接收者的数据，就在接收者的指针类型上定义该方法。否则，就在普通的值类型上定义方法。</p> <p>下面的例子 <code>pointer_value.go</code> 作了说明：<code>change()</code>接受一个指向 B 的指针，并改变它内部的成员；<code>write()</code> 通过拷贝接受 B 的值并只输出B的内容。注意 Go 为我们做了探测工作，我们自己并没有指出是否在指针上调用方法，Go 替我们做了这些事情。b1 是值而 b2 是指针，方法都支持运行了。</p> <p>示例 10.13 pointer_value.go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> B <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	thing <span class="token builtin">int</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>B<span class="token punctuation">)</span> <span class="token function">change</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> b<span class="token punctuation">.</span>thing <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>b B<span class="token punctuation">)</span> <span class="token function">write</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Sprint</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> <span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> b1 B <span class="token comment">// b1是值</span>
	b1<span class="token punctuation">.</span><span class="token function">change</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b1<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

	b2 <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>B<span class="token punctuation">)</span> <span class="token comment">// b2是指针</span>
	b2<span class="token punctuation">.</span><span class="token function">change</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b2<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">/* 输出：
{1}
{1}
*/</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div><p>试着在 <code>write()</code> 中改变接收者b的值：将会看到它可以正常编译，但是开始的 b 没有被改变。</p> <p>我们知道方法将指针作为接收者不是必须的，如下面的例子，我们只是需要 <code>Point3</code> 的值来做计算：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> Point3 <span class="token keyword">struct</span> <span class="token punctuation">{</span> x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> z <span class="token builtin">float64</span> <span class="token punctuation">}</span>
<span class="token comment">// A method on Point3</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>p Point3<span class="token punctuation">)</span> <span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">float64</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> math<span class="token punctuation">.</span><span class="token function">Sqrt</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>x<span class="token operator">*</span>p<span class="token punctuation">.</span>x <span class="token operator">+</span> p<span class="token punctuation">.</span>y<span class="token operator">*</span>p<span class="token punctuation">.</span>y <span class="token operator">+</span> p<span class="token punctuation">.</span>z<span class="token operator">*</span>p<span class="token punctuation">.</span>z<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>这样做稍微有点昂贵，因为 <code>Point3</code> 是作为值传递给方法的，因此传递的是它的拷贝，这在 Go 中是合法的。也可以在指向这个类型的指针上调用此方法（会自动解引用）。</p> <p>假设 <code>p3</code> 定义为一个指针：<code>p3 := &amp;Point{ 3, 4, 5}</code>。</p> <p>可以使用 <code>p3.Abs()</code> 来替代 <code>(*p3).Abs()</code>。</p> <p>像例子 10.10（method1.go）中接收者类型是 <code>*TwoInts</code> 的方法 <code>AddThem()</code>，它能在类型 <code>TwoInts</code> 的值上被调用，这是自动间接发生的。</p> <p>因此 <code>two2.AddThem</code> 可以替代 <code>(&amp;two2).AddThem()</code>。</p> <p>在值和指针上调用方法：</p> <p>可以有连接到类型的方法，也可以有连接到类型指针的方法。</p> <p>但是这没关系：对于类型 T，如果在 *T 上存在方法 <code>Meth()</code>，并且 <code>t</code> 是这个类型的变量，那么 <code>t.Meth()</code> 会被自动转换为 <code>(&amp;t).Meth()</code>。</p> <p><strong>指针方法和值方法都可以在指针或非指针上被调用</strong>，如下面程序所示，类型 <code>List</code> 在值上有一个方法 <code>Len()</code>，在指针上有一个方法 <code>Append()</code>，但是可以看到两个方法都可以在两种类型的变量上被调用。</p> <p>示例 10.14 methodset1.go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> List <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>l List<span class="token punctuation">)</span> <span class="token function">Len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span>        <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>l<span class="token punctuation">)</span> <span class="token punctuation">}</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>List<span class="token punctuation">)</span> <span class="token function">Append</span><span class="token punctuation">(</span>val <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">*</span>l <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span><span class="token operator">*</span>l<span class="token punctuation">,</span> val<span class="token punctuation">)</span> <span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// 值</span>
	<span class="token keyword">var</span> lst List
	lst<span class="token punctuation">.</span><span class="token function">Append</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;%v (len: %d)&quot;</span><span class="token punctuation">,</span> lst<span class="token punctuation">,</span> lst<span class="token punctuation">.</span><span class="token function">Len</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// [1] (len: 1)</span>

	<span class="token comment">// 指针</span>
	plst <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>List<span class="token punctuation">)</span>
	plst<span class="token punctuation">.</span><span class="token function">Append</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">&quot;%v (len: %d)&quot;</span><span class="token punctuation">,</span> plst<span class="token punctuation">,</span> plst<span class="token punctuation">.</span><span class="token function">Len</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// &amp;[2] (len: 1)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><h2 id="_10-6-4-方法和未导出字段"><a href="#_10-6-4-方法和未导出字段" class="header-anchor">#</a> 10.6.4 方法和未导出字段</h2> <p>考虑 <code>person2.go</code> 中的 <code>person</code> 包：类型 <code>Person</code> 被明确的导出了，但是它的字段没有被导出。例如在 <code>use_person2.go</code> 中 <code>p.firstName</code> 就是错误的。该如何在另一个程序中修改或者只是读取一个 <code>Person</code> 的名字呢？</p> <p>这可以通过面向对象语言一个众所周知的技术来完成：提供 getter 和 setter 方法。对于 setter 方法使用 Set 前缀，对于 getter 方法只使用成员名。</p> <p>示例 10.15 person2.go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> person

<span class="token keyword">type</span> Person <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	firstName <span class="token builtin">string</span>
	lastName  <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>p <span class="token operator">*</span>Person<span class="token punctuation">)</span> <span class="token function">FirstName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> p<span class="token punctuation">.</span>firstName
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>p <span class="token operator">*</span>Person<span class="token punctuation">)</span> <span class="token function">SetFirstName</span><span class="token punctuation">(</span>newName <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	p<span class="token punctuation">.</span>firstName <span class="token operator">=</span> newName
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>示例 10.16—use_person2.go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;./person&quot;</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	p <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>person<span class="token punctuation">.</span>Person<span class="token punctuation">)</span>
	<span class="token comment">// p.firstName undefined</span>
	<span class="token comment">// (cannot refer to unexported field or method firstName)</span>
	<span class="token comment">// p.firstName = &quot;Eric&quot;</span>
	p<span class="token punctuation">.</span><span class="token function">SetFirstName</span><span class="token punctuation">(</span><span class="token string">&quot;Eric&quot;</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span><span class="token function">FirstName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// Output: Eric</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p><strong>并发访问对象</strong></p> <p>对象的字段（属性）不应该由 2 个或 2 个以上的不同线程在同一时间去改变。如果在程序发生这种情况，为了安全并发访问，可以使用包 <code>sync</code>（参考第 9.3 节）中的方法。在第 14.17 节中我们会通过 goroutines 和 channels 探索另一种方式。</p> <h2 id="_10-6-5-内嵌类型的方法和继承"><a href="#_10-6-5-内嵌类型的方法和继承" class="header-anchor">#</a> 10.6.5 内嵌类型的方法和继承</h2> <p>当一个匿名类型被内嵌在结构体中时，匿名类型的可见方法也同样被内嵌，这在效果上等同于外层类型 <strong>继承</strong> 了这些方法：<strong>将父类型放在子类型中来实现亚型</strong>。这个机制提供了一种简单的方式来模拟经典面向对象语言中的子类和继承相关的效果，也类似 Ruby 中的混入（mixin）。</p> <p>下面是一个示例（可以在练习 10.8 中进一步学习）：假定有一个 <code>Engine</code> 接口类型，一个 <code>Car</code> 结构体类型，它包含一个 <code>Engine</code> 类型的匿名字段：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> Engine <span class="token keyword">interface</span> <span class="token punctuation">{</span>
	<span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	<span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> Car <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	Engine
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>我们可以构建如下的代码：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>Car<span class="token punctuation">)</span> <span class="token function">GoToWorkIn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// get in car</span>
	c<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	<span class="token comment">// drive to work</span>
	c<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	<span class="token comment">// get out of car</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>下面是 <code>method3.go</code> 的完整例子，它展示了内嵌结构体上的方法可以直接在外层类型的实例上调用：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
	<span class="token string">&quot;math&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> Point <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	x<span class="token punctuation">,</span> y <span class="token builtin">float64</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>p <span class="token operator">*</span>Point<span class="token punctuation">)</span> <span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">float64</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> math<span class="token punctuation">.</span><span class="token function">Sqrt</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>x<span class="token operator">*</span>p<span class="token punctuation">.</span>x <span class="token operator">+</span> p<span class="token punctuation">.</span>y<span class="token operator">*</span>p<span class="token punctuation">.</span>y<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> NamedPoint <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	Point
	name <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	n <span class="token operator">:=</span> <span class="token operator">&amp;</span>NamedPoint<span class="token punctuation">{</span>Point<span class="token punctuation">{</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">&quot;Pythagoras&quot;</span><span class="token punctuation">}</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>n<span class="token punctuation">.</span><span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 打印5</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p>内嵌将一个已存在类型的字段和方法注入到了另一个类型里：匿名字段上的方法“晋升”成为了外层类型的方法。当然类型可以有只作用于本身实例而不作用于内嵌“父”类型上的方法，</p> <p>可以覆写方法（像字段一样）：和内嵌类型方法具有同样名字的外层类型的方法会覆写内嵌类型对应的方法。</p> <p>在示例 10.18 method4.go 中添加：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>n <span class="token operator">*</span>NamedPoint<span class="token punctuation">)</span> <span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">float64</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> n<span class="token punctuation">.</span>Point<span class="token punctuation">.</span><span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">100.</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>现在 <code>fmt.Println(n.Abs())</code> 会打印 <code>500</code>。</p> <p>因为一个结构体可以嵌入多个匿名类型，所以实际上我们可以有一个简单版本的多重继承，就像：<code>type Child struct { Father; Mother}</code>。在第 10.6.7 节中会进一步讨论这个问题。</p> <p>结构体内嵌和自己在同一个包中的结构体时，可以彼此访问对方所有的字段和方法。</p> <p><strong>练习 10.8</strong> inheritance_car.go</p> <p>创建一个上面 <code>Car</code> 和 <code>Engine</code> 可运行的例子，并且给 <code>Car</code> 类型一个 <code>wheelCount</code> 字段和一个 <code>numberOfWheels()</code> 方法。</p> <p>创建一个 <code>Mercedes</code> 类型，它内嵌 <code>Car</code>，并新建 <code>Mercedes</code> 的一个实例，然后调用它的方法。</p> <p>然后仅在 <code>Mercedes</code> 类型上创建方法 <code>sayHiToMerkel()</code> 并调用它。</p> <h2 id="_10-6-6-如何在类型中嵌入功能"><a href="#_10-6-6-如何在类型中嵌入功能" class="header-anchor">#</a> 10.6.6 如何在类型中嵌入功能</h2> <p>主要有两种方法来实现在类型中嵌入功能：</p> <p>A：聚合（或组合）：包含一个所需功能类型的具名字段。</p> <p>B：内嵌：内嵌（匿名地）所需功能类型，像前一节 10.6.5 所演示的那样。</p> <p>为了使这些概念具体化，假设有一个 <code>Customer</code> 类型，我们想让它通过 <code>Log</code> 类型来包含日志功能，<code>Log</code> 类型只是简单地包含一个累积的消息（当然它可以是复杂的）。如果想让特定类型都具备日志功能，你可以实现一个这样的 <code>Log</code> 类型，然后将它作为特定类型的一个字段，并提供 <code>Log()</code>，它返回这个日志的引用。</p> <p>方式 A 可以通过如下方法实现（使用了第 10.7 节中的 <code>String()</code> 功能）：</p> <p>示例 10.19 embed_func1.go：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> Log <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	msg <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> Customer <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	Name <span class="token builtin">string</span>
	log  <span class="token operator">*</span>Log
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	c <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>Customer<span class="token punctuation">)</span>
	c<span class="token punctuation">.</span>Name <span class="token operator">=</span> <span class="token string">&quot;Barak Obama&quot;</span>
	c<span class="token punctuation">.</span>log <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Log<span class="token punctuation">)</span>
	c<span class="token punctuation">.</span>log<span class="token punctuation">.</span>msg <span class="token operator">=</span> <span class="token string">&quot;1 - Yes we can!&quot;</span>
	<span class="token comment">// shorter</span>
	c <span class="token operator">=</span> <span class="token operator">&amp;</span>Customer<span class="token punctuation">{</span><span class="token string">&quot;Barak Obama&quot;</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>Log<span class="token punctuation">{</span><span class="token string">&quot;1 - Yes we can!&quot;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
	<span class="token comment">// fmt.Println(c) &amp;{Barak Obama 1 - Yes we can!}</span>
	c<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;2 - After me the world will be a better place!&quot;</span><span class="token punctuation">)</span>
	<span class="token comment">//fmt.Println(c.log)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>Log<span class="token punctuation">)</span> <span class="token function">Add</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	l<span class="token punctuation">.</span>msg <span class="token operator">+=</span> <span class="token string">&quot;\n&quot;</span> <span class="token operator">+</span> s
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>Log<span class="token punctuation">)</span> <span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> l<span class="token punctuation">.</span>msg
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>Customer<span class="token punctuation">)</span> <span class="token function">Log</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span>Log <span class="token punctuation">{</span>
	<span class="token keyword">return</span> c<span class="token punctuation">.</span>log
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br></div></div><p>输出：</p> <div class="language- extra-class"><pre><code>1 - Yes we can!
2 - After me the world will be a better place!
</code></pre></div><p>相对的方式 B 可能会像这样：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> Log <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	msg <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> Customer <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	Name <span class="token builtin">string</span>
	Log
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	c <span class="token operator">:=</span> <span class="token operator">&amp;</span>Customer<span class="token punctuation">{</span><span class="token string">&quot;Barak Obama&quot;</span><span class="token punctuation">,</span> Log<span class="token punctuation">{</span><span class="token string">&quot;1 - Yes we can!&quot;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>
	c<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">&quot;2 - After me the world will be a better place!&quot;</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span>

<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>Log<span class="token punctuation">)</span> <span class="token function">Add</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	l<span class="token punctuation">.</span>msg <span class="token operator">+=</span> <span class="token string">&quot;\n&quot;</span> <span class="token operator">+</span> s
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>Log<span class="token punctuation">)</span> <span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> l<span class="token punctuation">.</span>msg
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>Customer<span class="token punctuation">)</span> <span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> c<span class="token punctuation">.</span>Name <span class="token operator">+</span> <span class="token string">&quot;\nLog:&quot;</span> <span class="token operator">+</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintln</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span>Log<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br></div></div><p>输出：</p> <div class="language- extra-class"><pre><code>Barak Obama
Log:1 - Yes we can!
2 - After me the world will be a better place!
</code></pre></div><p>内嵌的类型不需要指针，<code>Customer</code> 也不需要 <code>Add</code> 方法，它使用 <code>Log</code> 的 <code>Add</code> 方法，<code>Customer</code> 有自己的 <code>String</code> 方法，并且在它里面调用了 <code>Log</code> 的 <code>String</code> 方法。</p> <p>如果内嵌类型嵌入了其他类型，也是可以的，那些类型的方法可以直接在外层类型中使用。</p> <p>因此一个好的策略是创建一些小的、可复用的类型作为一个工具箱，用于组成域类型。</p> <h2 id="_10-6-7-多重继承"><a href="#_10-6-7-多重继承" class="header-anchor">#</a> 10.6.7 多重继承</h2> <p>多重继承指的是类型获得多个父类型行为的能力，它在传统的面向对象语言中通常是不被实现的（C++ 和 Python 例外）。因为在类继承层次中，多重继承会给编译器引入额外的复杂度。但是在 Go 语言中，通过在类型中嵌入所有必要的父类型，可以很简单的实现多重继承。</p> <p>作为一个例子，假设有一个类型 <code>CameraPhone</code>，通过它可以 <code>Call()</code>，也可以 <code>TakeAPicture()</code>，但是第一个方法属于类型 <code>Phone</code>，第二个方法属于类型 <code>Camera</code>。</p> <p>只要嵌入这两个类型就可以解决这个问题，如下所示：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> Camera <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>Camera<span class="token punctuation">)</span> <span class="token function">TakeAPicture</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> <span class="token string">&quot;Click&quot;</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> Phone <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>p <span class="token operator">*</span>Phone<span class="token punctuation">)</span> <span class="token function">Call</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> <span class="token string">&quot;Ring Ring&quot;</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> CameraPhone <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	Camera
	Phone
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	cp <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>CameraPhone<span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;Our new CameraPhone exhibits multiple behaviors...&quot;</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;It exhibits behavior of a Camera: &quot;</span><span class="token punctuation">,</span> cp<span class="token punctuation">.</span><span class="token function">TakeAPicture</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;It works like a Phone too: &quot;</span><span class="token punctuation">,</span> cp<span class="token punctuation">.</span><span class="token function">Call</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br></div></div><p>输出：</p> <div class="language- extra-class"><pre><code>Our new CameraPhone exhibits multiple behaviors...
It exhibits behavior of a Camera: Click
It works like a Phone too: Ring Ring
</code></pre></div><p><strong>练习 10.9</strong> point_methods.go：</p> <p>从 <code>point.go</code> 开始（第 10.1 节的练习）：使用方法来实现 <code>Abs()</code> 和 <code>Scale()</code>函数，<code>Point</code> 作为方法的接收者类型。也为 <code>Point3</code> 和 <code>Polar</code> 实现 <code>Abs()</code> 方法。完成了 <code>point.go</code> 中同样的事情，只是这次通过方法。</p> <p><strong>练习 10.10</strong> inherit_methods.go：</p> <p>定义一个结构体类型 <code>Base</code>，它包含一个字段 <code>id</code>，方法 <code>Id()</code> 返回 <code>id</code>，方法 <code>SetId()</code> 修改 <code>id</code>。结构体类型 <code>Person</code> 包含 <code>Base</code>，及 <code>FirstName</code> 和 <code>LastName</code> 字段。结构体类型 <code>Employee</code> 包含一个 <code>Person</code> 和 <code>salary</code> 字段。</p> <p>创建一个 <code>employee</code> 实例，然后显示它的 <code>id</code>。</p> <p><strong>练习 10.11</strong> magic.go：</p> <p>首先预测一下下面程序的结果，然后动手实验下：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">package</span> main

<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;fmt&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> Base <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>Base<span class="token punctuation">)</span> <span class="token function">Magic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;base magic&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>self Base<span class="token punctuation">)</span> <span class="token function">MoreMagic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	self<span class="token punctuation">.</span><span class="token function">Magic</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	self<span class="token punctuation">.</span><span class="token function">Magic</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> Voodoo <span class="token keyword">struct</span> <span class="token punctuation">{</span>
	Base
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>Voodoo<span class="token punctuation">)</span> <span class="token function">Magic</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">&quot;voodoo magic&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	v <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>Voodoo<span class="token punctuation">)</span>
	v<span class="token punctuation">.</span><span class="token function">Magic</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
	v<span class="token punctuation">.</span><span class="token function">MoreMagic</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><h2 id="_10-6-8-通用方法和方法命名"><a href="#_10-6-8-通用方法和方法命名" class="header-anchor">#</a> 10.6.8 通用方法和方法命名</h2> <p>在编程中一些基本操作会一遍又一遍的出现，比如打开（Open）、关闭（Close）、读（Read）、写（Write）、排序（Sort）等等，并且它们都有一个大致的意思：打开（Open）可以作用于一个文件、一个网络连接、一个数据库连接等等。具体的实现可能千差万别，但是基本的概念是一致的。在 Go 语言中，通过使用接口（参考 第 11 章），标准库广泛的应用了这些规则，在标准库中这些通用方法都有一致的名字，比如 <code>Open()</code>、<code>Read()</code>、<code>Write()</code>等。想写规范的 Go 程序，就应该遵守这些约定，给方法合适的名字和签名，就像那些通用方法那样。这样做会使 Go 开发的软件更加具有一致性和可读性。比如：如果需要一个 convert-to-string 方法，应该命名为 <code>String()</code>，而不是 <code>ToString()</code>（参考第 10.7 节）。</p> <h2 id="_10-6-9-和其他面向对象语言比较-go-的类型和方法"><a href="#_10-6-9-和其他面向对象语言比较-go-的类型和方法" class="header-anchor">#</a> 10.6.9 和其他面向对象语言比较 Go 的类型和方法</h2> <p>在如 C++、Java、C# 和 Ruby 这样的面向对象语言中，方法在类的上下文中被定义和继承：在一个对象上调用方法时，运行时会检测类以及它的超类中是否有此方法的定义，如果没有会导致异常发生。</p> <p>在 Go 语言中，这样的继承层次是完全没必要的：如果方法在此类型定义了，就可以调用它，和其他类型上是否存在这个方法没有关系。在这个意义上，Go 具有更大的灵活性。</p> <p>下面的模式就很好的说明了这个问题：</p> <p><img src="/blogs/assets/img/10.6.9_fig10.4.81e3114c.jpg" alt=""></p> <p>Go 不需要一个显式的类定义，如同 Java、C++、C# 等那样，相反地，“类”是通过提供一组作用于一个共同类型的方法集来隐式定义的。类型可以是结构体或者任何用户自定义类型。</p> <p>比如：我们想定义自己的 <code>Integer</code> 类型，并添加一些类似转换成字符串的方法，在 Go 中可以如下定义：</p> <div class="language-go line-numbers-mode"><pre class="language-go"><code><span class="token keyword">type</span> Integer <span class="token builtin">int</span>
<span class="token keyword">func</span> <span class="token punctuation">(</span>i <span class="token operator">*</span>Integer<span class="token punctuation">)</span> <span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> strconv<span class="token punctuation">.</span><span class="token function">Itoa</span><span class="token punctuation">(</span><span class="token function">int</span><span class="token punctuation">(</span><span class="token operator">*</span>i<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>在 Java 或 C# 中，这个方法需要和类 <code>Integer</code> 的定义放在一起，在 Ruby 中可以直接在基本类型 int 上定义这个方法。</p> <p><strong>总结</strong></p> <p>在 Go 中，类型就是类（数据和关联的方法）。Go 不知道类似面向对象语言的类继承的概念。继承有两个好处：代码复用和多态。</p> <p>在 Go 中，代码复用通过组合和委托实现，多态通过接口的使用来实现：有时这也叫 <strong>组件编程（Component Programming）</strong>。</p> <p>许多开发者说相比于类继承，Go 的接口提供了更强大、却更简单的多态行为。</p> <p><strong>备注</strong></p> <p>如果真的需要更多面向对象的能力，看一下 <a href="https://github.com/losalamos/goop" target="_blank" rel="noopener noreferrer"><code>goop</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 包（Go Object-Oriented Programming），它由 Scott Pakin 编写: 它给 Go 提供了 JavaScript 风格的对象（基于原型的对象），并且支持多重继承和类型独立分派，通过它可以实现你喜欢的其他编程语言里的一些结构。</p> <p><strong>问题 10.1</strong></p> <p>我们在某个类型的变量上使用点号调用一个方法：<code>variable.method()</code>，在使用 Go 以前，在哪儿碰到过面向对象的点号？</p> <p><strong>问题 10.2</strong></p> <p>a）假设定义： <code>type Integer int</code>，完成 <code>get()</code> 方法的方法体: <code>func (p Integer) get() int { ... }</code>。</p> <p>b）定义： <code>func f(i int) {}; var v Integer</code> ，如何就 v 作为参数调用f？</p> <p>c）假设 <code>Integer</code> 定义为 <code>type Integer struct {n int}</code>，完成 <code>get()</code> 方法的方法体：<code>func (p Integer) get() int { ... }</code>。</p> <p>d）对于新定义的 <code>Integer</code>，和 b）中同样的问题。</p></div></div> <div class="page-edit"><!----> <div class="last-updated"><span class="prefix">最近更新时间：</span> <span class="time">2021/03/16 19:48:24</span></div></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><a href="/blogs/golang/book-notes/the-way-to-go/751263e670a7f/" class="page-nav-centre page-nav-centre-prev"><div class="tooltip">匿名字段和内嵌结构体</div></a> <a href="/blogs/golang/book-notes/the-way-to-go/a37ef7bff9ee3/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">类型的 String() 方法和格式化描述符</div></a></div> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/blogs/golang/book-notes/the-way-to-go/751263e670a7f/" class="prev">匿名字段和内嵌结构体</a></span> <span class="next"><a href="/blogs/golang/book-notes/the-way-to-go/a37ef7bff9ee3/">类型的 String() 方法和格式化描述符</a>→
      </span></p></div></div></div> <div class="theme-vdoing-wrapper article-list bg-style-2"><div class="article-title"><a href="/blogs/archives/" class="fa fa-pencil-alt">
      最近更新
    </a></div> <div class="article-wrapper"><dl><dd>01</dd> <dt><div><a href="/blogs/golang/book-notes/the-way-to-go/b451871c7ebf3/"><div>总结和增强</div></a></div> <div class="date"><span>2021/03/16 19:29:10</span></div></dt></dl><dl><dd>02</dd> <dt><div><a href="/blogs/golang/book-notes/the-way-to-go/af1d6a84a8f0c/"><div>使用代理缓存</div></a></div> <div class="date"><span>2021/03/16 19:28:46</span></div></dt></dl><dl><dd>03</dd> <dt><div><a href="/blogs/golang/book-notes/the-way-to-go/49b0f32997236/"><div>版本 5 - 分布式程序</div></a></div> <div class="date"><span>2021/03/16 19:28:23</span></div></dt></dl> <div class="more-box"><a href="/blogs/archives/" class="more"><i class="fas fa-angle-double-right"></i>前往更多 ...
      </a></div></div></div> <div class="comments-wrapper" style="display:none;"><!----></div></main></div> <div class="footer-wrapper" data-v-ae53833e data-v-ae53833e><span class="footer-reco-theme" data-v-ae53833e><i class="iconfont reco-theme" data-v-ae53833e></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-ae53833e>vuepress-theme-reco@1.6.1</a> <a target="blank" href="https://doc.xugaoyi.com/" class="vdoing ml5" data-v-ae53833e>vuepress-theme-vdoing@1.7.2</a></span> <!----> <span class="footer-copyright" data-v-ae53833e><i class="iconfont reco-copyright" data-v-ae53833e></i> <a data-v-ae53833e><span data-v-ae53833e>凯小默</span> <span class="ml5" data-v-ae53833e>
          2019 - 2021
        </span></a></span> <span class="footer-view-site" data-v-ae53833e><i class="iconfont reco-eye" data-v-ae53833e></i> <span id="busuanzi_container_site_uv" data-v-ae53833e>
        访客数：<span id="busuanzi_value_site_uv" class="num" data-v-ae53833e>-</span></span> <span id="busuanzi_container_site_pv" class="ml5" data-v-ae53833e>
        访问量：<span id="busuanzi_value_site_pv" class="num" data-v-ae53833e>-</span></span></span> <!----></div> <!----></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-c6073ba8 data-v-c6073ba8><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-c6073ba8><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-c6073ba8></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-c6073ba8></path></svg></div><!----><div></div><APlayer audio="" fixed="true" mini="true" theme="#3eaf7c" loop="loop" order="random" preload="auto" volume="1" mutex="true" lrc-type="0" list-folded="true" list-max-height="250" storage-name="vuepress-plugin-meting" id="aplayer-fixed"></APlayer></div></div>
    <script src="/blogs/assets/js/app.b6577c57.js" defer></script><script src="/blogs/assets/js/2.44f167e6.js" defer></script><script src="/blogs/assets/js/22.b69b7288.js" defer></script><script src="/blogs/assets/js/10.3a18c1d1.js" defer></script>
  </body>
</html>
